/**
 * @class
 * @description 对方法进行操作
 */
class MethodOperate {
    /**
     * @function
     * @description 函数节流（通过时间戳）
     * @param {Function} func -  需要执行的函数
     * @param {Number} wait -  节流的时间
     * @return {Function} 返回一个节流后的函数
     * @example
     *   class.throttleDate(()=>{},100)
     */
    static throttleDate<T extends (...args: any[]) => any>(func: T, wait: number): (...args: Parameters<T>) => void {
        let lastCallTime = 0;
        return (...args: Parameters<T>) => {
            const now = Date.now();
            if (now - lastCallTime >= wait) {
                func(...args);
                lastCallTime = now;
            }
        };
    }
    /**
     * @function
     * @description 函数节流（通过定时器）
     * @param {Function} func -  需要执行的函数
     * @param {Number} wait -  节流的时间
     * @return {Function} 返回一个节流后的函数
     * @example
     *   class.throttleTimeOut(()=>{},100)
     */
    static throttleTimeOut<T extends (...args: any[]) => any>(func: T, wait: number): (...args: Parameters<T>) => void {
        let timeout: ReturnType<typeof setTimeout> | null = null;
        return (...args: Parameters<T>) => {
            if (!timeout) {
                timeout = setTimeout(() => {
                    timeout = null;
                    func(...args);
                }, wait);
            }
        };
    }
    /**
     * @function
     * @description 函数防抖
     * @param {Function} func -  需要执行的函数
     * @param {Number} wait -  防抖的时间
     * @param {Boolean} immediate -  是否立即执行
     * @return {Function} 返回一个防抖后的函数
     * @example
     *   class.debounce(()=>{},100,true)
     */
    static debounce<T extends (...args: any[]) => any>(
        func: T,
        wait: number,
        immediate: boolean = false
    ): (...args: Parameters<T>) => void {
        let timeout: ReturnType<typeof setTimeout> | null = null;
        return function (this: any, ...args: Parameters<T>) {
            const context = this;
            const later = () => {
                timeout = null;
                if (!immediate) {
                    func.apply(context, args);
                }
            };
            const callNow = immediate && !timeout;
            if (timeout) {
                clearTimeout(timeout);
            }
            timeout = setTimeout(later, wait);
            if (callNow) {
                func.apply(context, args);
            }
        };
    }
}
export default MethodOperate;
